/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package simulation;

/**
 *  
 * @author Gravena
 */
public class Exponential implements Distribution {
    private double rate; /* Rate of the exponential distribution */
    private static final double delta = 0.000001;
    
    /**
     * Insertion sort 
     */
    public static void sort(double[] v) {
        int i;
        double item;
        int iHole;
        for(i = 1;i < v.length;i++) {
            item = v[i];
            iHole = i;
            
            /* Double comparison, with delta tolerance */
            while(iHole > 0 && v[iHole - 1] - item > delta) {
                v[iHole] = v[--iHole];                
            }
            v[iHole] = item;
        }
    }
    
    public static void printArray(double[] v) {
        System.out.printf("{");
        for(int i=0;i<v.length-1;i++) {
            System.out.printf("%f, ",v[i]);
        }
        System.out.printf("%f}\n", v[v.length-1]);        
    }

    public Exponential(double rate) {
        this.rate = rate;
    }
    
    public Exponential() {
        this.rate = 1.0;
    }
    
    /**
     * Calculates a exponential distributed arrive time
     * @return A exponential distributed arrive time
     */
    public double getArriveTime() {
        double U = Math.random();
        return -rate*Math.log(1 - U);
    }
    
    public double getArriveTime(double U) {
        return -Math.log(1 - U)/rate;
    }
    
    public double[][] getGNUPlotData(int nArrives) {
        double [][] data = new double[2][nArrives];
        
        for(int i=0;i<nArrives;i++) {
            double U = Math.random();
            data[0][i] = U;
            data[1][i] = this.getArriveTime(U);
        }        
        
        return data;
    }
    
    /**
     * Build a array with exponential distributed arrival times
     * @param nArrives Number of desired arrives
     * @return A double array containing the arrival times from each of the nArrives events
     */
    public double[] getPoissonProcess(int nArrives) {
        double array[] = new double[nArrives];
        int i;
        
        for(i=0;i<nArrives;i++) {
            array[i] = this.getArriveTime();
        }
        
        return array;        
    }  
    
    @Override
    public double[] getTimes(int N) {
        return this.getPoissonProcess(N);
    }
    
    @Override
    public double[] getParamList() {
        double[] param = new double[1];
        param[0] = this.rate;
        return param;
    }
    
    public static double calcMean(double times[]) {
        double sum = 0.0;
        int i;
        for(i=0;i<times.length;i++) {
            sum += times[i];
        }
        
        return sum/(double)i;
    }
    
    @Override
    public String toString() {
        return "Exponential(" + this.rate + ")";
    }
    
    public static void main(String args[]) {
        Exponential exp = new Exponential(2.0);
        int n = 100;
        double [][] data;
        data = exp.getGNUPlotData(100);
                
        for(int i=0;i<n;i++) {
            String temp = "" + data[0][i] + " " + data[1][i];
            temp = temp.replaceAll(",", ".");
            System.out.printf("%s\n", temp);
        }        
        
        System.out.println("Mean = " + Exponential.calcMean(data[1]));
    }
}
